
#ifndef BEZIER_H_
#define BEZIER_H_

#include "curva.h"
#include "combinatorio.h"
#include <vector>


class Coord;

class Bezier : public Curva {
   private:
      std::vector<Coord> pcontrol;

      float longitudSegmento;
      static Combinatorio combinatorio;

   public:
      /*
       * Construye una curva bezier con una cantidad "puntos" de puntos de control
       * Donde la cantidad de puntos es igual a la cantidad de coordenadas del vector
       *
       * Precondicion:
       *    La cantidad de elementos debe cumplir
       *
       *    cant > 0
       *    cant % grado() (esto equivale a que cant == n*grado + 1)
       *
       * */       
      Bezier(const std::vector<Coord> &pcontrol); 

      explicit Bezier(const Bezier& aCopiar);

      /*
       * Retorna true si
       *    cant % grado() == 1
       * sino, false.
       * */
      static bool satisfacePrecond(size_t cant);

      size_t grado() const;

      virtual ~Bezier();
      virtual Coord centro() const;

      /*
       * Retorna una coordenada de la curva, en funcion del parametro i
       *
       * Precondicion:
       *    0 <= i <= 1
       * */
      virtual Coord operator()(float i) const;

      /*
       * Retorna una coordenada que representa un vector tangente a la curva, 
       * en funcion del parametro i
       *
       * Precondicion:
       *    0 <= i <= 1
       * */
      virtual Coord tangente(float i) const;

      /*
       * Retorna una lista con las coordenadas de los puntos de control
       * de la curva Bezier.
       * El objeto retornado sera valido mientras la curva Bezier no sea
       * modificada.
       * */
      const std::vector<Coord>& getPuntosControl() const;

   private:

      float coefBase(float u, int numBase) const; 
      float coefBaseDerivada(float u, int numBase) const;

      /*
       * Determina, en funcion del parametro i que parametro local u discretizado
       * le corresponde y que puntos de control p[j], p[j+1], ... seran
       * utilizados en el calculo de la coordenada segun i.
       *
       * Precondicion:
       *    0 <= i <= 1
       * */
      void parametros(float i, float &u, int &j) const;
};

#endif
